﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Xml.Serialization;
using LetsDoIt.BO.ResponseMessages;
using LetsDoIt.Common;
using Newtonsoft.Json;

namespace LetsDoIt.BO
{
    /// <summary>
    /// factory class used for comunication with web service - trash points
    /// </summary>
	public class WastesServiceFactory
	{
        /// <summary>
        /// Upload a trash point to server
        /// </summary>
        /// <param name="caseinfo">caseInfo object</param>
        /// <param name="username">username</param>
        /// <param name="md5pass">md5 hashed password</param>
        /// <returns>response as ResponseWaste</returns>
		public static ResponseWaste UploadCase(CaseInfo caseinfo, string username, string md5pass, bool publishAsTest)
		{
			try
			{
			    caseinfo.IsTest = publishAsTest;

				HttpWebRequest webReq = HttpWebRequest.Create(WebServiceNames.WS_BASE_ADDRESSS + WebServiceNames.WASTE_ADDRESS) as HttpWebRequest;
				if (webReq != null)
				{
					webReq.AllowAutoRedirect = true;
					webReq.AllowWriteStreamBuffering = true;
					webReq.Method = "POST";
					webReq.ContentType = "text/xml";
					webReq.Credentials = new NetworkCredential(username, md5pass);
					webReq.PreAuthenticate = true; 

					
					string body = string.Format(WebServiceNames.WASTE_TYPE,
                        caseinfo.BagEq,
						caseinfo.Description,
						caseinfo.Diameter,
						caseinfo.Heigth,
						caseinfo.ID,
						caseinfo.DifficultAccess.ToString().ToLower(),
						caseinfo.DifficultAccessOnRain.ToString().ToLower(),
                        caseinfo.IsDispersed.ToString().ToLower(),
                        caseinfo.IsTest.ToString().ToLower(),
                        caseinfo.Length,
						caseinfo.Latitude,
						caseinfo.Longitude,
						caseinfo.PaperContent,
						caseinfo.GlassContent,
						caseinfo.MetalContent,
						caseinfo.NotRecyclableContent,
						caseinfo.PlasticContent,
						caseinfo.MatterialsContent,
						caseinfo.RubberContent,
						100,
						caseinfo.CaseDateTime.ToString("yyyy-MM-ddTHH:mm:ss"),
                        caseinfo.Width
						);

					using (StreamWriter writer = new StreamWriter(webReq.GetRequestStream()))
					{
						writer.Write(body);
					}


					WebResponse webResponse = webReq.GetResponse();

					string contents = string.Empty;
					using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
					{
						contents = reader.ReadToEnd();
						webResponse.Close();
					}

					XmlSerializer ser = new XmlSerializer(typeof(ResponseWaste));
					ResponseWaste result = ser.Deserialize(new StringReader(contents)) as ResponseWaste;
					return result;
				}
			}
			catch(WebException ex)
			{
				//Log error
				HttpWebResponse res = (HttpWebResponse)ex.Response;
				if (res != null)
				{
					HttpStatusCode status = res.StatusCode;
					string contentResponse;
					using (Stream stm = res.GetResponseStream())
					{
						using (StreamReader reader = new StreamReader(stm))
						{
							contentResponse = reader.ReadToEnd();
						}
					}
					ErrorDetail detail = JsonConvert.DeserializeObject<ErrorDetail>(contentResponse);
					if (detail != null)
						Program.Log.Error(ex.Status + " " + detail.Detail);
				}
				else
				{
					Program.Log.Error(ex.ToString());
				}
			}
			catch (Exception ex)
			{
				//Log error
				Program.Log.Error(ex.ToString());
			}
			return null;
		}


        /// <summary>
        /// Upload multiple cases to server
        /// </summary>
        /// <param name="cases">list of cases</param>
        /// <param name="username">username</param>
        /// <param name="md5pass">md5 hashed pass</param>
        /// <returns>response as a list of ResponseWaste</returns>
        public static List<ResponseWaste> UploadCases(List<CaseInfo> cases, string username, string md5pass, bool publishAsTest)
		{
			//todo - implementation
            throw new NotImplementedException();
			return new List<ResponseWaste>();
		}


        /// <summary>
        /// Upload an image and attach it to a trash point
        /// </summary>
        /// <param name="imageFile">image file name</param>
        /// <param name="wasteId">trash point ID from sever</param>
        /// <param name="username">user name</param>
        /// <param name="md5pass">md5 hashed password</param>
        /// <returns>response of type ResponseImage</returns>
	    public static ResponseImage UploadImage(string imageFile, string wasteId, string username, string md5pass)
		{
			try
			{
				HttpWebRequest webReq = HttpWebRequest.Create(WebServiceNames.WS_BASE_ADDRESSS + string.Format(WebServiceNames.IMAGE_ADDRESS, wasteId)) as HttpWebRequest;
				if (webReq != null)
				{
					webReq.AllowAutoRedirect = true;
					webReq.AllowWriteStreamBuffering = true;
					webReq.Method = "POST";
					webReq.ContentType = "application/octet-stream";
					webReq.Credentials = new NetworkCredential(username, md5pass);
					webReq.PreAuthenticate = true;


					using (FileStream fs =File.OpenRead(imageFile))
					{
						Stream str = webReq.GetRequestStream();

						int read;
						byte[] buffer = new byte[4096];
						while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
						{
							str.Write(buffer, 0, read);
						}
						str.Close();
					}

					WebResponse webResponse = webReq.GetResponse();
					string contents = string.Empty;
					using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
					{
						contents = reader.ReadToEnd();
						webResponse.Close();
					}

					if (!string.IsNullOrEmpty(contents))
					{
						XmlSerializer ser = new XmlSerializer(typeof (ResponseImage));
						ResponseImage result = ser.Deserialize(new StringReader(contents)) as ResponseImage;
						return result;
					}
					else
					{
						return null;
					}
				}
			}
			catch (WebException ex)
			{
				//Log error
				HttpWebResponse res = (HttpWebResponse)ex.Response;
				if (res != null)
				{
					HttpStatusCode status = res.StatusCode;
					string contentResponse;
					using (Stream stm = res.GetResponseStream())
					{
						using (StreamReader reader = new StreamReader(stm))
						{
							contentResponse = reader.ReadToEnd();
						}
					}
					ErrorDetail detail = JsonConvert.DeserializeObject<ErrorDetail>(contentResponse);
					if (detail != null)
						Program.Log.Error(ex.Status + " " + detail.Detail);
				}
				else
				{
					Program.Log.Error(ex.ToString());
				}
			}
			catch (Exception ex)
			{
				//Log error
				Program.Log.Error(ex.ToString());
			}
			return null;
		}

	}

    /// <summary>
    /// class used to deserialize error detail
    /// </summary>
	public class ErrorDetail
	{
		public string Detail { get; set; }
	}
}
